/*
 * InputGenerators.cpp
 *
 *  Created on: Sep 17, 2013
 *      Author: sjelic
 */

#include "InputGenerators.h"
#include "coveringPackingMiscellaneous.h"

void ig::message(std::string message)
{
	std::cout<<std::endl;
	std::cout<<message;
	std::cout<<std::endl;
}

ig::BernoulliMPCInputGenerator::BernoulliMPCInputGenerator(float dP, float dC, unsigned int npc, unsigned int ncc, unsigned int nv)
{

	if(nv==0)
	{
		ig::message("ERROR: The number of variables  must be positive. EXIT.");
		exit(0);
	}

	if(npc==0)
	{
		ig::message("STATUS: You are going to generate an instance of the pure fractional Covering Linear Program.");
	}
	if(ncc==0)
	{
		ig::message("STATUS: You are going to generate an instance of the pure fractional Packing Linear Program.");
	}
	probability_of_one_pack = dP;
	probability_of_one_cov = dC;
	num_constr_pack = npc;
	num_constr_cov = ncc;
	num_var = nv;


}

void ig::BernoulliMPCInputGenerator::createInputFile(std::string filePath)
{
		std::ofstream file;
		file.open(filePath.c_str(),std::ios::out);
		std::stringstream packingMatrix;
		std::string packingMatrixString;

		//file<<std::endl;
		//file<<std::endl;

		if(!file.is_open())
		{
			ig::message("ERROR: File: "+filePath+" can not be opened. EXIT.");
			exit(0);
		}
		std::default_random_engine generator;

		std::bernoulli_distribution distributionPack(probability_of_one_pack);
		unsigned int iter=0;
		int numNonzeroPacking=0;
		//srand((unsigned int)time());
		while(iter<num_constr_pack*num_var)
		{
			if (distributionPack(generator))
			{
				packingMatrix<<iter/num_var<<" "<<iter%num_var<<" "<<1<<std::endl;
				numNonzeroPacking++;
			}
			iter++;
		}
		packingMatrixString=packingMatrix.str();

		//long currentPosition = file.tellp();
		std::stringstream packHeaderLine;
		std::string packHeaderLineString;

		packHeaderLine<<num_constr_pack<<" "<<num_var<<" "<<numNonzeroPacking<<std::endl;
		packHeaderLineString = packHeaderLine.str();



		//file.seekp(0,std::ios_base::beg);
		//file.write(packLineString.c_str(),packLineString.size());


		//file.seekp(currentPosition);
		std::stringstream coveringMatrix;
		std::string coveringMatrixString;
		std::bernoulli_distribution distributionCov(probability_of_one_cov);
		iter=0;
		int numNonzeroCovering=0;
		while(iter<num_constr_cov*num_var)
		{
			if (distributionCov(generator))
			{
				coveringMatrix<<iter/num_var<<" "<<iter%num_var<<" "<<1<<std::endl;
				numNonzeroCovering++;
			}
			iter++;

		}
		coveringMatrixString=coveringMatrix.str();

		std::stringstream coverHeaderLine;
		std::string coverHeaderLineString;

		coverHeaderLine<<num_constr_cov<<" "<<num_var<<" "<<numNonzeroCovering<<std::endl;
		coverHeaderLineString = coverHeaderLine.str();
		file<<packHeaderLineString<<coverHeaderLineString;
		file<<packingMatrixString<<coveringMatrixString;

		//packing right-hand vector
		for(unsigned int i=0; i<num_constr_pack; i++)
		{
			file<<1<<std::endl;

		}
		//covering right-hand vector
		for(unsigned int i=0; i<num_constr_cov; i++)
		{
			file<<1<<std::endl;
		}
		//price vector
		for(unsigned int i=0; i<num_var; i++)
		{
			file<<1<<std::endl;
		}
		file.close();

}

ig::KleeMintyMPCInputGenerator::KleeMintyMPCInputGenerator(unsigned int nv, unsigned int npc,unsigned int ncc)
{
	if(nv==0)
	{
		ig::message("ERROR: A number of variables in Klee-Minty instance must be a positive integer. EXIT.");
		exit(0);
	}

	if(npc==0)
	{
		ig::message("WARNING: A number of packing constraints in Klee-Minty instance must be a positive integer. It's going to be set on number of variables: "+nv);
		npc=nv;
	}
	if(ncc>0)
	{
		ig::message("WARNING: Klee-Minty instance is a pure Packing Linear Program. A number of covering constraint is going to be set on ZERO.");
		ncc=0;
	}

	if(npc!=nv)
	{
		if(npc>nv) npc=nv;
		else nv=npc;
		ig::message("WARNING: A number of variables and a number of packing constraints in Klee-Minty instance must be equal. It's going to be set on the smaller one: "+nv);
	}



	num_constr_pack = npc;
	num_constr_cov = ncc;
	num_var = nv;
}

void ig::KleeMintyMPCInputGenerator::createInputFile(std::string filePath)
{
	std::ofstream file;
	file.open(filePath.c_str(),std::ios::out);
	std::stringstream packingMatrix;
	std::string packingMatrixString;

	if(!file.is_open())
	{
		std::cout<<std::endl;
		std::cout<<"ERROR: File: "<<filePath<<" can not be opened. EXIT.";
		std::cout<<std::endl;
		exit(0);

	}

	for(unsigned int i=0; i<num_constr_pack; i++)
	{
		for(unsigned int j=0; j<i; j++)
		{
			packingMatrix<<i<<" "<<j<<" "<<pow(2,i+1-j)<<std::endl;
		}
		packingMatrix<<i<<" "<<i<<" "<<1<<std::endl;
	}
	packingMatrixString=packingMatrix.str();
	std::stringstream packHeaderLine;
	std::string packHeaderLineString;

	packHeaderLine<<num_constr_pack<<" "<<num_var<<" "<<num_var*(num_var+1)/2<<std::endl;
	packHeaderLineString = packHeaderLine.str();


	std::stringstream coverHeaderLine;
	std::string coverHeaderLineString;

	coverHeaderLine<<num_constr_cov<<" "<<num_var<<" "<<0<<std::endl;
	coverHeaderLineString = coverHeaderLine.str();
	file<<packHeaderLineString<<coverHeaderLineString;
	file<<packingMatrixString;

	//packing right-hand vector
	for(unsigned int i=0; i<num_constr_pack; i++)
	{
		file<<pow(5,i+1)<<std::endl;
	}
	//price vector
	for(unsigned int i=0; i<num_var; i++)
	{
		file<<pow(2,num_var-i-1)<<std::endl;
	}
	file.close();

}




ig::BernoulliMPCInputGenerator::~BernoulliMPCInputGenerator()
{
}

ig::KleeMintyMPCInputGenerator::~KleeMintyMPCInputGenerator()
{
}

